#include <QCoreApplication>
#include <QFuture>
#include <QtConcurrentMap>
#include <vector>
#include <functional>
#include <iostream>
#include <cmath>

struct interval_t
{
    double a;
    double b;
};

struct trapezoidal_integrator_map_t
{
    typedef double result_type;

    result_type operator()(const interval_t &i)
    {
        return (i.b - i.a) * (std::sin(i.a) + std::sin(i.b)) / 2.0;
    }
};

// it's really nice that i can't use reduce functor with mappedReduced
// due to QTBUG-22710, which exists since 2011
struct integrator_reduce_t
{
    typedef void result_type;

    result_type operator()(double &result, const double &x)
    {
        result += x;
    }
};

void reduce(double &result, const double &x)
{
    result += x;
}

int main(int argc, char **argv)
{
    QCoreApplication a(argc, argv);

    const double lower_bound = 0;
    const double upper_bound = 2;
    const double step = 0.0001;

    std::vector<interval_t> intervals;
    for (double x = lower_bound; x < upper_bound - step; x += step)
    {
        interval_t interval = {x, x + step};
        intervals.push_back(interval);
    }

    QFuture<double> result = QtConcurrent::mappedReduced(intervals.begin(), intervals.end(),
                                                         trapezoidal_integrator_map_t(),
                                                         reduce);
    std::cout << result.result() << std::endl;

    return 0;
}
